TBDIR = './tests/',

function writeComplex(cmplx, f)
  fd = mopen(TBDIR + f, 'wt');
  mfprintf(fd, '(%20.14e, %20.14e)\n', real(cmplx), imag(cmplx));
  mclose(fd);
endfunction

function [cmplx]=loadComplex(f)
  fd = mopen(TBDIR + f, 'r');
  L = mfscanf(-1, fd, '(%lg, %lg)\n')
  cmplx = (L(:,1) + %i*L(:,2));
  mclose(fd);
endfunction

function [parts]=loadParts(f)
  fd = mopen(TBDIR + f, 'r');
  parts = mfscanf(-1, fd, '(%lg, %lg)\n')
  mclose(fd);
endfunction

function [err]=cppErr(n)
  sci = loadParts(n + '.sci.txt');
  cpp = loadParts(n + '.cpp.txt');
  tt = abs(cpp - sci);
  err = sum(tt(:, 1) + tt(:, 2));
endfunction

// Create data
dataset1 = (rand(100, 1) * 10 - 5) + %i * (rand(100, 1) * 10 - 5);
dataset2 = rand(100, 1) * 2 - 1;
dataset3 = rand(100, 1) * 360 - 180;
dataset4 = 1 ./ (rand(100, 1) * 2 - 1);
writeComplex(dataset1, 'dataset1.txt');
writeComplex(dataset2, 'dataset2.txt');
writeComplex(dataset3, 'dataset3.txt');
writeComplex(dataset4, 'dataset4.txt');
flist = [
'add' ; 'sub' ; 'neg' ; 'mlt' ; 'div' ; 'inv' ; 'pow' ; 'abs' ; 'arg' ;
'real' ; 'imag' ; 'sqrt' ; 'ln' ; 'exp' ; 'log10' ; 'logx' ;
'sin' ; 'sind' ; 'cos' ; 'cosd' ; 'tan' ; 'tand' ; 'sec' ; 'secd' ;
'csc' ; 'cscd' ; 'cot' ; 'cotd' ; 'sinc' ; 'sincn' ;
'asin' ; 'asind' ; 'acos' ; 'acosd' ; 'atan' ; 'atand' ; 'asec' ;
'asecd' ; 'acsc' ; 'acscd' ; 'acot' ; 'acotd' ;
'sinh' ; 'cosh' ; 'tanh' ; 'sech' ; 'csch' ; 'coth' ;
'asinh' ; 'acosh' ; 'atanh' ; 'asech' ; 'acsch' ; 'acoth' ;
];

// Addition test.
addres = dataset1(1:50) + dataset1(51:100);
writeComplex(addres, 'add.sci.txt');
// Subtraction test.
subres = dataset1(1:50) - dataset1(51:100);
writeComplex(subres, 'sub.sci.txt');
// Negation test.
negres = -dataset1;
writeComplex(negres, 'neg.sci.txt');
// Multiplication test.
mltres = dataset1(1:50) .* dataset1(51:100);
writeComplex(mltres, 'mlt.sci.txt');
// Division test.
divres = dataset1(1:50) ./ dataset1(51:100);
writeComplex(divres, 'div.sci.txt');
// Inversion test.
invres = 1.0 ./ dataset1;
writeComplex(invres, 'inv.sci.txt');
// Exponentiation test.
powres = dataset1(1:50) .^ dataset1(51:100);
writeComplex(powres, 'pow.sci.txt');
// Absolute value test.
absres = abs(dataset1);
writeComplex(absres, 'abs.sci.txt');
// Argument value test.
argres = atan(imag(dataset1), real(dataset1));
writeComplex(argres, 'arg.sci.txt');
// Real part test.
realres = real(dataset1);
writeComplex(realres, 'real.sci.txt');
// Imaginary part test.
imagres = imag(dataset1);
writeComplex(imagres, 'imag.sci.txt');
// Square root test.
sqrtres = sqrt(dataset1);
writeComplex(sqrtres, 'sqrt.sci.txt');
// Natural logarithm test.
lnres = log(dataset1);
writeComplex(lnres, 'ln.sci.txt');
// Natural exponentiation test.
expres = exp(dataset1);
writeComplex(expres, 'exp.sci.txt');
// Base 10 logarithm test.
logres = log10(dataset1);
writeComplex(logres, 'log10.sci.txt');
// Base X logarithm test.
logxres = log(dataset1(2:2:100)) ./ log(dataset1(1:2:99));
writeComplex(logxres, 'logx.sci.txt');

// Sine test.
sinres = sin(dataset1);
writeComplex(sinres, 'sin.sci.txt');
sindres = sind(dataset2);
writeComplex(sindres, 'sind.sci.txt');
// Cosine test.
cosres = cos(dataset1);
writeComplex(cosres, 'cos.sci.txt');
cosdres = cosd(dataset2);
writeComplex(cosdres, 'cosd.sci.txt');
// Tangent test.
tanres = tan(dataset1);
writeComplex(tanres, 'tan.sci.txt');
tandres = tand(dataset2);
writeComplex(tandres, 'tand.sci.txt');
// Secant test.
secres = sec(dataset1);
writeComplex(secres, 'sec.sci.txt');
secdres = secd(dataset2);
writeComplex(secdres, 'secd.sci.txt');
// Cosecant test.
cscres = csc(dataset1);
writeComplex(cscres, 'csc.sci.txt');
cscdres = cscd(dataset2);
writeComplex(cscdres, 'cscd.sci.txt');
// Cotangent test.
cotres = cotg(dataset1);
writeComplex(cotres, 'cot.sci.txt');
cotdres = cotd(dataset2);
writeComplex(cotdres, 'cotd.sci.txt');
// Sinc test.
sincres = sinc(dataset1);
writeComplex(sincres, 'sinc.sci.txt');
sincnres = sinc(%pi * dataset1);
writeComplex(sincnres, 'sincn.sci.txt');
// ArcSine test.
asinres = asin(dataset1);
writeComplex(asinres, 'asin.sci.txt');
asindres = asind(dataset2);
writeComplex(asindres, 'asind.sci.txt');
// ArcCosine test.
acosres = acos(dataset1);
writeComplex(acosres, 'acos.sci.txt');
acosdres = acosd(dataset2);
writeComplex(acosdres, 'acosd.sci.txt');
// ArcTangent test.
atanres = atan(dataset1);
writeComplex(atanres, 'atan.sci.txt');
atandres = atand(dataset3);
writeComplex(atandres, 'atand.sci.txt');
// ArcSecant test.
asecres = asec(dataset1);
writeComplex(asecres, 'asec.sci.txt');
asecdres = asecd(dataset4);
writeComplex(asecdres, 'asecd.sci.txt');
// ArcCosecant test.
acscres = acsc(dataset1);
writeComplex(acscres, 'acsc.sci.txt');
acscdres = acscd(dataset4);
writeComplex(acscdres, 'acscd.sci.txt');
// ArcCotangent test.
acotres = acot(dataset1);
writeComplex(acotres, 'acot.sci.txt');
acotdres = acotd(dataset3);
writeComplex(acotdres, 'acotd.sci.txt');

// Hyperbolic Sine test.
sinhres = sinh(dataset1);
writeComplex(sinhres, 'sinh.sci.txt');
// Hyperbolic Cosine test.
coshres = cosh(dataset1);
writeComplex(coshres, 'cosh.sci.txt');
// Hyperbolic Tangent test.
tanhres = tanh(dataset1);
writeComplex(tanhres, 'tanh.sci.txt');
// Hyperbolic Secant test.
sechres = sech(dataset1);
writeComplex(sechres, 'sech.sci.txt');
// Hyperbolic Cosecant test.
cschres = csch(dataset1);
writeComplex(cschres, 'csch.sci.txt');
// Hyperbolic Cotangent test.
cothres = coth(dataset1);
writeComplex(cothres, 'coth.sci.txt');
// Hyperbolic ArcSine test.
asinhres = asinh(dataset1);
writeComplex(asinhres, 'asinh.sci.txt');
// Hyperbolic ArcCosine test.
acoshres = acosh(dataset1);
writeComplex(acoshres, 'acosh.sci.txt');
// Hyperbolic ArcTangent test.
atanhres = atanh(dataset1);
writeComplex(atanhres, 'atanh.sci.txt');
// Hyperbolic ArcSecant test.
asechres = asech(dataset1);
writeComplex(asechres, 'asech.sci.txt');
// Hyperbolic ArcCosecant test.
acschres = acsch(dataset1);
writeComplex(acschres, 'acsch.sci.txt');
// Hyperbolic ArcCotangent test.
acothres = acoth(dataset1);
writeComplex(acothres, 'acoth.sci.txt');

// Run cpp executable
chdir('bin');
unix_w('complex_tb');
chdir('..');

// Get errors
ieee(2);
fd = mopen(TBDIR + '/ERROR_REPORT.txt', 'wt');
mfprintf(fd, 'Func     Error\n');
for func = flist'
  err = cppErr(func);
  ss = sprintf(' %-8s %g', func, err);
  mfprintf(fd, '%s\n', ss);
  disp(ss);
end
mclose(fd);
